package deprecated;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

/**
 * unused class
 * @author Sabrina Maenz
 *
 */
public class DistanceSetArray {

		private String source;
		private String tmsource;
		
		private int lenDiff;
		private int editDist;
		private int lensourcePhrase;
		private int lentmsourcePhrase;
		
		private double maxFMS;
		
		private ArrayList<String> sourceListPhrase;
		private ArrayList<String> tmsourceListPhrase;
		private ArrayList<String> sourceListChar;
		private ArrayList<String> tmsourceListChar;
		private ArrayList<String> editHistory;
		
		private int[][] distanceMat;
		
		
		/**
		 * @param sourceSystem.out.println("i: "+i+" ind: "+ind);
		 * @param TMsource
		 */
		
		//changed Data-Types to String[]
		public DistanceSetArray(String[] source, String[] TMsource){
			
		//	this.source = source;
		//	this.tmsource = TMsource;
			
			/**
			 * TODO: This 'String preprocessing' is highly experimental.
			 */
		//	String[] sourceWords = this.source.split(" ");
		//	String[] tmsourceWords = this.tmsource.split(" ");
			 
			this.sourceListPhrase = new ArrayList<String>(Arrays.asList(source));
			this.tmsourceListPhrase = new ArrayList<String>(Arrays.asList(TMsource));
			
			this.lensourcePhrase = this.sourceListPhrase.size();
			this.lentmsourcePhrase = this.tmsourceListPhrase.size();
			
			this.lenDiff = Math.abs(this.sourceListPhrase.size()-this.tmsourceListPhrase.size());
			
		
		}
		public ArrayList<String> getEditHistory(){
			return this.editHistory;
		}
		
		public int getSourceLen(){
			return this.lensourcePhrase;
		}
		
		public int getTMSourceLen(){
			return this.lentmsourcePhrase;
		}
		
		public String getSource(){
			return this.source;
		}
		
		public String getTMSource(){
			return this.tmsource;
		}
		
		public int getlenDiff(){
			return this.lenDiff;
		}
		
		public ArrayList<String> getSourceList(){
			return this.sourceListPhrase;
		}
		
		public ArrayList<String> getTMSourceList(){
			return this.tmsourceListPhrase;
		}
		
		/**
		 * Upper bound of FMS based on length difference
		 * @return long containing the maxFMS
		 */
		public double getMaxFMS(){
			double div = (double)Math.max(getSourceLen(), getTMSourceLen());
			this.maxFMS = 1 - ((double)this.lenDiff / div);
			return this.maxFMS;
		}
		
		/**
		 * Optional function if we need to compare on a char basis
		 */
		public void computeSourceListChar(){
			
			String[] sourceChars = this.source.toLowerCase().split("");
			String[] tmsourceChars = this.tmsource.toLowerCase().split("");
			 
			this.sourceListChar = new ArrayList<String>(Arrays.asList(sourceChars));
			this.tmsourceListChar = new ArrayList<String>(Arrays.asList(tmsourceChars));
			
		}
		
		public ArrayList<String> getSourceListChar(){
			return this.sourceListChar;
		}
		
		public ArrayList<String> getTMSourceListChar(){
			return this.tmsourceListChar;
		} 
		

		/**
		 * Implementation for the EditDistance, O(words(a)*words(b)), as fast as possible as far as I know.
		 * Realization by a matrix which stores minimal distances.
		 * This might still be very slow for our purposes but we'll see.
		 * @return Edit or Levenshtein Distance for the two strings in the Set (source, TM source)
		 */
		public int getEditDistancePhrase(){
			
			int[][] distanceMat = new int[this.getSourceLen()+1][this.getTMSourceLen()+1];
			
		    for(int i=0; i<=this.getSourceLen(); i++){
		        distanceMat[i][0]= i;
		    }
		    
		    for(int j=0; j<=this.getTMSourceLen(); j++){
		        distanceMat[0][j]= j;
		    }
		    
		    for(int j=1; j<=this.getTMSourceLen(); j++){
		    	for(int i=1; i<=this.getSourceLen(); i++){
		    		if(this.getSourceList().get(i-1).equals(this.getTMSourceList().get(j-1))){
		    			distanceMat[i][j]=distanceMat[i-1][j-1];
		    		}else{
		    			 distanceMat[i][j]= minimum((distanceMat[i-1][j]+1),(distanceMat[i][j-1]+1),(distanceMat[i-1][j-1]+1));
		    		}
		    	}
		    }
			
			this.editDist = distanceMat[this.getSourceLen()][this.getTMSourceLen()];
		    return this.editDist;
		}

		/**
		 * Private function to provide the matrix to backtrack
		 * @return Edit Distance Matrix
		 */
		private void getEditDistanceMatrix(){
			
			int[][] distanceMat = new int[this.getSourceLen()+1][this.getTMSourceLen()+1];
			
		    for(int i=0; i<=this.getSourceLen(); i++){
		        distanceMat[i][0]= i;
		    }
		    
		    for(int j=0; j<=this.getTMSourceLen(); j++){
		        distanceMat[0][j]= j;
		    }
		    
		    for(int j=1; j<=this.getTMSourceLen(); j++){
		    	for(int i=1; i<=this.getSourceLen(); i++){
		    		if(this.getSourceList().get(i-1).equals(this.getTMSourceList().get(j-1))){
		    			distanceMat[i][j]=distanceMat[i-1][j-1];
		    		}else{
		    			 distanceMat[i][j]= minimum((distanceMat[i-1][j]+1),(distanceMat[i][j-1]+1),(distanceMat[i-1][j-1]+1));
		    		}
		    	}
		    }
			
			this.distanceMat = distanceMat;
		}
		
		/**
		 * recursive function to backtrack edit operations
		 * @param i
		 * @param j
		 * @return
		 */
		private ArrayList<String> backtrace(int i, int j){
			
			if(i>0 && this.distanceMat[i-1][j] + 1 == this.distanceMat[i][j]){
				editHistory.add(" Insertion ");
				return backtrace(i-1, j);
			}
			if(j>0 && this.distanceMat[i][j-1] + 1 == this.distanceMat[i][j]){
				editHistory.add(" Deletion ");
				return backtrace(i, j-1);
			}
			if(i>0 && j>0 && this.distanceMat[i-1][j-1] + 1 == this.distanceMat[i][j]){
				editHistory.add(" Replacement ");
				return backtrace(i-1, j-1);
			}
			if(i>0 && j>0 && this.distanceMat[i-1][j-1]  == this.distanceMat[i][j]){
				editHistory.add(" Match ");
				return backtrace(i-1, j-1);
	    	}
			return editHistory;
	    }
	    
	    
		public ArrayList<String> getBacktrace(){
			this.editHistory = new ArrayList<String>();
			getEditDistanceMatrix();
	    	backtrace(this.getSourceLen(),this.getTMSourceLen());
	    	Collections.reverse(this.editHistory);
	    	return this.editHistory;
		}
		
		
		
		private static int minimum(int a, int b, int c){
			return Math.min(Math.min(a, b),c);
		}
		
		
		/**
		 * TODO:Implementing the editDistance on a char basis, this will be a nightmare performance wise for longer sentences
		 * @return
		 */
		public int getEditDistanceChar(){
			return 0;
		}
		
		
		
	}
